<template>
  <div class="padding-16">
    <a-card class="general-card" title="菜单管理">
      <a-form
        ref="refSearchForm"
        :model="searchForm"
        auto-label-width
      >
        <a-row :gutter="16">
          <a-col :span="8">
            <a-form-item field="name" label="菜单名称">
              <a-input v-model="searchForm.name" placeholder="请输入菜单名称"/>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item field="status" label="状态">
              <a-select v-model="searchForm.status" :options="statusOptions" placeholder="全部"/>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item>
              <a-space :size="16">
                <a-button type="primary" @click="handleSearch">
                  <template #icon>
                    <icon-search/>
                  </template>
                  查询
                </a-button>
                <a-button @click="$refs.refSearchForm.resetFields()">
                  <template #icon>
                    <icon-refresh/>
                  </template>
                  重置
                </a-button>
              </a-space>
            </a-form-item>
          </a-col>
        </a-row>
      </a-form>
      <a-divider style="margin-top: 0"/>
      <a-space style="margin-bottom: 16px">
        <a-button size="small" type="primary" @click="handleEdit({}, 'add')">
          <template #icon>
            <icon-plus/>
          </template>
          新增
        </a-button>
        <a-button size="small" @click="handleExpandAll()">展开/折叠</a-button>
      </a-space>
      <a-table
        ref="refTable"
        bordered
        row-key="id"
        default-expand-all-rows
        :data="tableData"
        :loading="pageLoading"
        :pagination="false"
      >
        <template #columns>
          <a-table-column title="菜单名称" data-index="menu_name"></a-table-column>
          <a-table-column title="类型" data-index="menu_type">
            <template #cell="{ record }">
              <a-button v-if="record.menu_type === 'M'" type="outline" size="mini">目录</a-button>
              <a-button v-if="record.menu_type === 'C'" type="outline" size="mini" status="success">菜单</a-button>
              <a-button v-if="record.menu_type === 'A'" type="outline" size="mini" status="warning">按钮</a-button>
            </template>
          </a-table-column>
          <a-table-column title="图标" data-index="menu_icon"></a-table-column>
          <a-table-column title="权限标识" data-index="scopes"></a-table-column>
          <a-table-column title="状态" data-index="status">
            <template #cell="{ record }">
              <DictBadge :options="statusOptions" :value="record.status"/>
            </template>
          </a-table-column>
          <a-table-column title="排序" data-index="sort"></a-table-column>
          <a-table-column title="更新时间" data-index="update_time"></a-table-column>
          <a-table-column title="操作" :width="220">
            <template #cell="{ record }">
              <a-button type="text" @click="handleEdit(record, 'edit')">编辑</a-button>
              <a-button type="text" @click="handleEdit(record, 'add')">新增</a-button>
              <a-popconfirm content="删除后不可恢复，确定要删除吗？" @ok="handleDelete(record)">
                <a-button v-if="record.id !== 10000" type="text" status="danger">删除</a-button>
              </a-popconfirm>
            </template>
          </a-table-column>
        </template>
      </a-table>
    </a-card>

    <!-- 新增 & 编辑 弹窗 -->
    <a-modal
      v-model:visible="dialogVisible"
      width="680px"
      :title="`${formState.id ? '编辑' : '创建'}菜单`"
      :footer="false">
      <a-form
        ref="formRef"
        :model="formState"
        :rules="formRules"
        auto-label-width
        @submit="handleSubmit"
      >
        <a-form-item label="菜单类型" field="menu_type">
          <a-radio-group v-model="formState.menu_type">
            <a-radio v-for="item in typeOptions" :key="item.value" :value="item.value">{{ item.label }}</a-radio>
          </a-radio-group>
        </a-form-item>

        <a-form-item label="上级菜单" field="pid">
          <a-tree-select
            v-model="formState.pid"
            :data="departOptions"
            :field-names="fieldNames"
            placeholder="请选择上级菜单"
          ></a-tree-select>
        </a-form-item>
        <a-form-item label="菜单名称" field="menu_name">
          <a-input v-model="formState.menu_name" placeholder="请输入菜单名称"></a-input>
        </a-form-item>
        <!-- 目录&菜单 -->
        <template v-if="['M', 'C'].includes(formState.menu_type)">
          <a-form-item label="菜单图标" field="menu_icon">
            <a-input v-model="formState.menu_icon" placeholder="点击选择图标" :maxlength="20"/>
          </a-form-item>
          <a-form-item label="路由路径"
                       field="paths"
                       extra="访问的路由地址，如：`user`，如外网地址需内链访问则以`http(s)://`开头">
            <a-input v-model="formState.paths" placeholder="请输入路由路径" :maxlength="200"/>
          </a-form-item>
          <a-row v-if="formState.menu_type === 'C'" :gutter="16">
            <a-col :span="24">
              <a-form-item
                label="组件路径"
                field="component"
                extra="访问的组件路径，如：`user/setting`，默认在`views`目录下"
                :rules="[{required: true, message: '组件路径不能为空', trigger: 'change'}]"
              >
                <a-input v-model="formState.component" placeholder="请输入组件路径" :maxlength="200"/>
              </a-form-item>
            </a-col>
            <a-col :span="24">
              <a-form-item
                label="路由参数"
                field="params"
                extra='访问路由的默认传递参数，如：`{"id": 1, "name": "admin"}`或`id=1&name=admin`'
              >
                <a-input v-model="formState.params" placeholder="请输入路由参数" :maxlength="200"/>
              </a-form-item>
            </a-col>

            <a-col :span="12">
              <a-form-item
                label="权限标识"
                field="scopes"
                extra="将作为server端API验权使用，如`auth.admin/user`，请谨慎修改"
              >
                <a-input v-model="formState.scopes" placeholder="请输入权限标识" :maxlength="200"/>
              </a-form-item>
            </a-col>

            <a-col :span="12">
              <a-form-item
                label="是否缓存"
                field="is_cache"
                extra="选择缓存则会被`keep-alive`缓存"
                :rules="[{required: true, message: '是否缓存不能为空', trigger: 'change'}]"
              >
                <a-radio-group v-model="formState.is_cache">
                  <a-radio :value="1">缓存</a-radio>
                  <a-radio :value="0">不缓存</a-radio>
                </a-radio-group>
              </a-form-item>
            </a-col>
          </a-row>
          <a-row :gutter="16">
            <a-col :span="12">
              <a-form-item label="显示状态" field="is_show" extra="隐藏则不会出现在侧边栏，但仍可以访问">
                <a-radio-group v-model="formState.is_show">
                  <a-radio :value="1">显示</a-radio>
                  <a-radio :value="0">隐藏</a-radio>
                </a-radio-group>
              </a-form-item>
            </a-col>

            <a-col :span="12">
              <a-form-item label="状态" field="status" extra="停用则不会出现在侧边栏，也不能被访问">
                <a-radio-group v-model="formState.status">
                  <a-radio v-for="item in statusOptions" :key="item.value" :value="item.value">{{
                      item.label
                    }}
                  </a-radio>
                </a-radio-group>
              </a-form-item>
            </a-col>

            <a-col :span="12">
              <a-form-item label="排序" field="sort" extra="数值越小，越靠前">
                <a-input-number v-model="formState.sort" :min="1" :max="999" mode="button"/>
              </a-form-item>
            </a-col>
          </a-row>
        </template>
        <!-- 按钮 -->
        <template v-if="formState.menu_type === 'A'">
          <a-form-item
            label="权限标识"
            field="scopes"
            extra="将作为server端API验权使用，如`auth.admin/user`，请谨慎修改"
          >
            <a-input v-model="formState.scopes" placeholder="请输入权限标识" :maxlength="200"/>
          </a-form-item>
          <a-form-item label="排序" field="sort" extra="数值越小，越靠前">
            <a-input-number v-model="formState.sort" :min="1" :max="999" mode="button"/>
          </a-form-item>
        </template>
        <div class="form-footer">
          <a-button key="submit" html-type="submit" type="primary" :loading="pageLoading">确 定</a-button>
          <a-button class="ml-24" @click="handleCancel">取 消</a-button>
        </div>
      </a-form>
    </a-modal>
  </div>
</template>

<script lang="ts">
import {defineComponent} from "vue";
import MennuAPI from "@/api/system/menu";
import {statusOptions} from "@/enums/status";
import {getLabel, typeOptions} from "@/enums/menu";

export default defineComponent({
  data() {
    return {
      pageLoading: false,
      statusOptions,
      typeOptions,
      isExpandAll: false,
      tableData: [],
      searchForm: {
        name: "",
        status: ""
      },
      // 部门树选择
      departOptions: [],
      fieldNames: {
        title: "menu_name",
        key: "id",
        children: "children"
      },
      // 创建弹窗
      dialogVisible: false,
      formState: {
        id: undefined,
        pid: 0,
        menu_type: 'M', // 类型
        menu_name: undefined,
        menu_icon: undefined,
        sort: 10,
        scopes: undefined, // 菜单权限
        paths: undefined, // 路径
        component: undefined, // 菜单组件
        params: undefined, // 菜单参数
        is_cache: 0, // 是否缓存
        is_show: 1,
        status: 1,
      },
      formRules: {
        pid: [{required: true, message: "上级菜单不能为空", trigger: "change"}],
        menu_type: [{required: true, message: "菜单类型不能为空", trigger: "blur"}],
        menu_name: [{required: true, min: 2, message: "至少2个字符", trigger: "change"}],
        paths: [{required: true, message: "菜单路径不能为空", trigger: "change"}],
        is_show: [{required: true, message: "显示状态不能为空", trigger: "change"}],
        status: [{required: true, message: "状态不能为空", trigger: "change"}]
      }
    };
  },
  mounted() {
    this.fetchTableData();
  },
  methods: {
    getLabel,
    handleExpandAll() {
      this.isExpandAll = !this.isExpandAll
      this.$refs.refTable.expandAll(this.isExpandAll)
    },
    async fetchTableData(extraParam = {}) {
      this.pageLoading = true;
      try {
        let params = {
          ...this.searchForm
        };
        if (extraParam) {
          params = {
            ...params,
            ...extraParam
          };
        }
        const {data, code} = await MennuAPI.getList(params);

        if (code === 200 && data) {
          this.tableData = data || [];
          if (!this.searchForm.name && this.searchForm.status === '') {
            this.departOptions = [{id: 0, menu_name: "顶级菜单", children: data || []}]
          }
        }
      } catch (err) {
        console.warn(err);
        // Message.error("出了点小问题，请稍后重试！");
      }
      this.pageLoading = false;
    },
    handleSearch() {
      this.fetchTableData();
    },
    // 操作
    handleDelete(rowData) {
      if (!rowData.id) return;

      MennuAPI.del(rowData.id).then(res => {
        const {code, msg} = res;

        if (code === 200) {
          this.$message.success(msg || "删除成功！");
          this.fetchTableData();
        } else {
          this.$message.error(msg || "出了点小问题，请稍后重试！");
        }
      });
    },
    // 创建表单
    handleEdit(rowData: any, type = "add") {
      this.dialogVisible = true;
      if (rowData.id && type === "edit") {
        this.formState = {
          id: rowData.id,
          pid: rowData.pid,
          menu_type: rowData.menu_type,
          menu_name: rowData.menu_name,
          menu_icon: rowData.menu_icon,
          sort: rowData.sort,
          scopes: rowData.scopes,
          paths: rowData.paths,
          component: rowData.component,
          params: rowData.params,
          is_cache: rowData.is_cache,
          is_show: rowData.is_show,
          status: rowData.status
        };

      } else {
        this.formState.pid = rowData.id;
      }
    },
    handleCancel() {
      if (this.$refs.formRef) {
        this.$refs.formRef.resetFields();
      }
      this.dialogVisible = false;
      this.formState = {
        id: undefined,
        pid: 0,
        menu_type: 'M', // 类型
        menu_name: undefined,
        menu_icon: undefined,
        sort: 10,
        scopes: undefined, // 菜单权限
        paths: undefined, // 路径
        component: undefined, // 菜单组件
        params: undefined, // 菜单参数
        is_cache: 0, // 是否缓存
        is_show: 1,
        status: 1,
      }
    },
    async handleSubmit({values, errors}) {
      console.log("values:", values, "\nerrors:", errors);
      if (!errors) {
        const params = {
          ...this.formState
        }

        this.pageLoading = true
        try {

          if (params.id) {
            await MennuAPI.update(params)
          } else {
            await MennuAPI.create(params)
          }

          this.$message.success('保存成功！')
          await this.fetchTableData()
          this.handleCancel()
        } catch (err) {
          // you can report use errorHandler or other
        } finally {
          this.pageLoading = false;
        }
      }
    }
  }
});
</script>


<style scoped lang="less">
.form-footer {
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
